package com.nami.pchat.infra.gateway;

import cn.hutool.core.collection.CollUtil;
import com.nami.basic.dto.MultiResponse;
import com.nami.basic.dto.SingleResponse;
import com.nami.gate.external.basic.cache.user.UserDeviceRel;
import com.nami.pchat.domain.gateway.UserGateway;
import com.nami.pchat.infra.cache.user.caffeine.UserCache;

import com.nami.ucenter.client.api.UserReadClient;
import com.nami.ucenter.client.response.UserDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.redis.utils.RedisUtils;
import org.redisson.api.RLock;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class UserGatewayImpl implements UserGateway {

    @DubboReference
    UserReadClient userReadFacade;

    @Override
    public UserDeviceRel getUserById(String appKey, String userId) {
        if (StringUtils.isBlank(appKey) || StringUtils.isBlank(userId)) {
            return null;
        }
        UserDeviceRel user = UserCache.get(userId);
        if (user == null) {
            RLock lock = RedisUtils.getClient().getLock("nami:" + appKey + ":user:lock:" + userId);
            try {
                lock.lock();
                // 只要登录了。就存入了redis
//                UserWrap exist = cacheService.getOnrUser(appKey, userId);
                SingleResponse<UserDTO> response = userReadFacade.getByUserId(appKey, userId);
                if (!response.isSuccess()) {
                    return null;
                }
                UserDTO exist = response.getData();
                if (exist == null) {
                    return null;
                }
                UserDeviceRel userWithDevice = new UserDeviceRel();
                userWithDevice.setUserId(userId);
                userWithDevice.setAppKey(exist.getAppKey());
                userWithDevice.setNick(exist.getNickname());
                userWithDevice.setAvatar(exist.getAvatarUrl());
                userWithDevice.setStatus(exist.getStatus());

                UserCache.add(userId, userWithDevice);
                return userWithDevice.clone();
            } finally {
                lock.unlock();
            }
        }
        return user;
    }

    public List<UserDeviceRel> getUsers(List<String> userIds) {
        if (CollUtil.isEmpty(userIds)) {
            return null;
        }

        List<String> qryIds = new ArrayList<>(userIds.size());
        List<UserDeviceRel> result = new ArrayList<>(userIds.size());
        for (String userId : userIds) {
            UserDeviceRel user = UserCache.get(userId);
            if (user != null) {
                result.add(user);
                continue;
            }
            qryIds.add(userId);
        }
        if (CollUtil.isEmpty(qryIds)) {
            return result;
        }
        MultiResponse<UserDTO> response = userReadFacade.listByUserIds(qryIds);
        if (response.isSuccess()) {
            List<UserDTO> users = response.getData();
            for (UserDTO user : users) {
                if (user == null) {
                    return null;
                }
                UserDeviceRel userWrap = new UserDeviceRel();
                userWrap.setUserId(user.getUserId());
                userWrap.setAppKey(user.getAppKey());
                userWrap.setNick(user.getNickname());
                userWrap.setAvatar(user.getAvatarUrl());
                userWrap.setStatus(user.getStatus());

                UserCache.add(user.getUserId(), userWrap);
                result.add(userWrap.clone());
            }
        }
        return result;
    }


    @Override
    public Map<String, UserDeviceRel> mapOfUsers(String appKey, List<String> userIds) {
        if (CollUtil.isEmpty(userIds) || StringUtils.isBlank(appKey)) {
            return new HashMap<>();
        }

        List<UserDeviceRel> users = this.getUsers(userIds);
        if (CollUtil.isEmpty(userIds)) {
            return new HashMap<>();
        }
        users.forEach(System.out::println);
        return users.stream()
            .collect(Collectors.toMap(UserDeviceRel::getUserId,
                Function.identity()));
    }


}
